ArrayList<E>

data structures object-oriented programming apis & frameworks software engineering algorithms java
ArrayList is a resizable, indexed sequence in Java’s Collections Framework that stores elements in a contiguous array. It provides fast random access, amortized constant-time appends, and flexible capacity management. It is generic, allowing type-safe storage of any reference type, and supports rich list operations (add, get, set, remove, iterate). Unlike arrays, ArrayList grows automatically; unlike LinkedList, it offers O(1) indexed access but O(n) insertions/deletions in the middle. It is not thread-safe by default and uses fail-fast iterators.

What Is ArrayList<E>?

ArrayList<E> is a dynamic array implementation of the List interface in Java. It stores elements contiguously in memory and automatically resizes as elements are added. The generic type parameter E specifies the type of elements stored, providing compile-time type safety.

Key Characteristics

  • Dynamic sizing: Grows (and can be trimmed) as needed; capacity is managed separately from size.
  • Indexed access: Fast random access via get(index) and set(index, value) in O(1) time.
  • Insertion/Removal: Appending at the end is amortized O(1). Inserting or removing in the middle requires shifting elements, so it is O(n).
  • Order-preserving: Maintains insertion order and allows duplicates and null values.
  • Generic: Type parameter E enforces type safety (no casts on retrieval).
  • Not synchronized: By default not thread-safe; use wrappers or other collections for concurrency.
  • Fail-fast iterators: Iterators detect concurrent structural modification and typically throw ConcurrentModificationException.

Common Operations

// Create with inferred type
ArrayList<String> names = new ArrayList<>();

// Create with initial capacity (reduces resizing if you know the size)
ArrayList<Integer> nums = new ArrayList<>(100);

// Add elements
names.add("Ada");
names.add("Grace");
names.add(1, "Linus"); // insert at index 1

// Access and modify
String first = names.get(0);       // O(1)
names.set(2, "Hopper");            // O(1)

// Remove by index or by value
names.remove(1);                    // O(n) shift
names.remove("Ada");                // O(n) search then shift

// Search
boolean hasGrace = names.contains("Grace"); // O(n)
int idx = names.indexOf("Grace");           // O(n)

// Bulk operations
ArrayList<String> more = new ArrayList<>();
more.add("Edsger");
more.add("Barbara");
names.addAll(more);

// Iteration
for (String s : names) {
    System.out.println(s);
}

// Using an Iterator (supports safe removal during iteration)
Iterator<String> it = names.iterator();
while (it.hasNext()) {
    String s = it.next();
    if (s.startsWith("B")) {
        it.remove(); // safe structural change
    }
}

// Sorting
names.sort(Comparator.naturalOrder());
// or
Collections.sort(names);

// Convert to array
String[] arr = names.toArray(new String[0]);

// Capacity management
names.ensureCapacity(1000);
names.trimToSize();

Performance Overview

  • Access (get/set by index): O(1)
  • Append add(e): Amortized O(1); occasional resize is O(n) but infrequent
  • Insert/Remove at index: O(n) due to shifting elements
  • Search (contains/indexOf): O(n)
  • Iteration: O(n)

Internally, capacity grows when needed (commonly by ~1.5x). Pre-sizing with an appropriate initial capacity or using ensureCapacity can reduce reallocations and copying.

When to Use ArrayList<E>

  • You need fast random access to elements by index.
  • You primarily append to the end rather than insert/remove in the middle.
  • You want an order-preserving, resizable array with type safety.

Consider LinkedList<E> when frequent insertions/removals in the middle dominate and indexed access is rare. Prefer arrays when the size is fixed and primitive storage is required (to avoid autoboxing overhead).

Generics and Type Safety

ArrayList<E> uses generics for compile-time type checks. For example, ArrayList<String> rejects non-String elements. Due to type erasure, the runtime representation does not retain E’s type parameter, but compile-time safety prevents class cast errors on retrieval.

Iteration and Fail-Fast Behavior

Iterators over an ArrayList are fail-fast: if the list is structurally modified outside the iterator after its creation, operations like next() may throw ConcurrentModificationException. Use the iterator’s remove() for safe removal during iteration.

Thread Safety

  • Not synchronized: Multiple threads modifying the same ArrayList require external synchronization.
  • Options include Collections.synchronizedList(new ArrayList<>()) or using CopyOnWriteArrayList for read-heavy, write-light workloads.

Common Pitfalls and Tips

  • Middle insertions/removals are O(n); consider data structure choice if this is frequent.
  • subList(from, to) returns a view backed by the original list; structural changes to either affect the other. To copy, use new ArrayList<>(list.subList(...)).
  • contains and remove(Object) rely on equals; implement it properly for custom types.
  • ArrayList holds references; when storing boxed primitives (e.g., Integer), consider boxing overhead.
  • Use ensureCapacity when the target size is known to minimize resizes; call trimToSize to reduce memory footprint when growth is complete.

Context from Referenced By

Context from Related Topics
Pop Quiz
Topic: ArrayList<E>
Level: 1
True or False:

The subList(from, to) method on an ArrayList returns a view backed by the original list, so structural changes to either list are reflected in the other.

Topic: ArrayList<E>
Level: 1
Multiple Choice:

You plan to append about 1,000 elements to a Java ArrayList and want to minimize internal resizing and copying. Which call should you make on the list before adding the elements?

Topic: ArrayList<E>
Level: 1
Fill in the Blank:

Iterators over a Java ArrayList are _____, meaning they throw ConcurrentModificationException if the list is structurally modified outside the iterator.

Topic: ArrayList<E>
Level: 2
True or False:

ArrayList<E> can store primitive types like int directly without boxing.

Topic: ArrayList<E>
Level: 2
Multiple Choice:

In Java's ArrayList<E>, how does the contains(Object o) method determine whether the list contains a given element?

Topic: ArrayList<E>
Level: 2
Fill in the Blank:

Accessing an element by index in a Java ArrayList runs in _____ time.

Topic: ArrayList<E>
Level: 3
True or False:

Java's ArrayList maintains insertion order and allows duplicate and null elements.

Topic: ArrayList<E>
Level: 3
Multiple Choice:

In Java's ArrayList, what is the effect of calling trimToSize()?

Topic: ArrayList<E>
Level: 3
Fill in the Blank:

To obtain a thread-safe wrapper around an existing ArrayList, use Collections._____ (list).

Topic: ArrayList<E>
Level: 4
True or False:

Due to type erasure, ArrayList<String> and ArrayList<Integer> have the same runtime Class object.

Topic: ArrayList<E>
Level: 4
Multiple Choice:

While iterating over a Java ArrayList with an Iterator, how can you safely remove elements that meet a condition without triggering ConcurrentModificationException?

Topic: ArrayList<E>
Level: 4
Fill in the Blank:

In Java's ArrayList, inserting or removing in the middle is O(n) because it requires _____ elements to maintain contiguity.

Topic: ArrayList<E>
Level: 5
True or False:

In Java's ArrayList, size is the current number of elements, whereas capacity is the length of the internal array and can be greater than size.

Topic: ArrayList<E>
Level: 5
Multiple Choice:

In Java, given ArrayList<String> names, what does the call String[] arr = names.toArray(new String[0]); produce?

Topic: ArrayList<E>
Level: 5
Fill in the Blank:

ArrayList<E> stores its elements in a _____ array, enabling O(1) indexed access.

Next Topic
implements
1.0

List<E>
ArrayList is a concrete implementation of the List<E> interface; studying ArrayList naturally introduces the List contract, shared methods, and polymorphic usage across Java collections.
implements
0.98

List<E>
ArrayList<E> is a concrete implementation of the List<E> interface, so learning ArrayList naturally leads to understanding the List contract and its common operations used across Java APIs.
implements
0.98

List<E>
ArrayList<E> implements the List<E> interface in the Java Collections Framework, defining the operations and contracts clients should rely on.
implements
0.98

List<E>
ArrayList<E> is a concrete implementation of the List interface in Java’s Collections Framework, so studying ArrayList naturally leads to the List abstraction and its contract.
implements
0.98

List<E>
ArrayList<E> implements the List interface, providing the behaviors and operations defined by List, such as indexed access and ordered iteration.
implements
0.98

Java.util.list<E>
ArrayList<E> implements the List interface, fulfilling its ordered-collection contract and method set (add, get, set, remove, iteration). Studying List clarifies the semantics and guarantees that ArrayList must honor.
implements
0.97

List<E>
Studying ArrayList<E> leads to the List<E> interface it implements, clarifying the general contract and behaviors shared across list implementations.
implements
0.95

List<E>
ArrayList<E> is a primary concrete implementation of the List<E> interface in Java; learning the List contract clarifies the operations and guarantees ArrayList must fulfill and enables polymorphic use with other List implementations.
related_to
0.86

Algorithmic Complexity Big O
Big-O notation provides the framework to analyze and communicate the time/space costs of ArrayList operations (e.g., O(1) random access, amortized O(1) append, O(n) middle insert/remove), informing trade-offs versus other lists and capacity strategies.
returns
0.84

Java Iterators
ArrayList exposes traversal via iterator() and listIterator(), leading to Java's fail-fast Iterator and ListIterator usage patterns.